//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "camdrv.h"
#include "camplus.h"

ECode CCamera::Control(
    /* [in] */ Handle32 nControlCode,
    /* [in] */ const MemoryBuf & inBuffer,
    /* [out] */ MemoryBuf * pOutBuffer,
    /* [out] */ IEvent * * ppCompletionEvent)
{
    ECode ec = NOERROR;
    Camera_Format *pFormat;

    switch (nControlCode) {
        case 0:
            // Initialize camera device
            ec = g_CameraDriver.CamDrv_Initialize();
            break;

        case 1:
            // Quit camera device
            g_CameraDriver.CamDrv_Quit();
            break;

        case 2:
            // Get photo information and data
            // If continue snap is set, maybe there are more than 1 photo
            if (pOutBuffer == NULL) {
                return E_INVALID_ARGUMENT;
            }
            if (pOutBuffer->GetCapacity() < (int)sizeof(Camera_Photo)) {
                ec = E_OUT_OF_MEMORY;
                break;
            }
            ec = g_CameraDriver.CamDrv_GetSnapshotFrames((Camera_Photo *)pOutBuffer->GetPayload());

            pOutBuffer->SetUsed(sizeof(Camera_Photo));
            break;

        case 3:
            // Begin preview
            if (NULL == ppCompletionEvent) {
                ec = E_INVALID_ARGUMENT;
                break;
            }
            ec = g_CameraDriver.CamDrv_BeginPreview(ppCompletionEvent);
            break;

        case 4:
            // Stop preview
            ec = g_CameraDriver.CamDrv_StopPreview();
            break;

        case 5:
            // Release the memory of frames, except the default preview buffer.
            g_CameraDriver.CamDrv_ReleaseFrames();
            break;

        case 6:
            // Set many formats for camera device, such as photo quality, brightness ...
            if (inBuffer.GetCapacity() < (int)sizeof(Camera_Format)) {
                ec = E_OUT_OF_MEMORY;
                break;
            }

            pFormat = (Camera_Format *)inBuffer.GetPayload();

            ec = g_CameraDriver.CamDrv_SetAppFormat(pFormat->nID,
                    pFormat->wParam, pFormat->lParam);
            break;

        case 7:
            // Get many formats for camera device, such as photo quality, brightness ...
            if (pOutBuffer == NULL) {
                return E_INVALID_ARGUMENT;
            }
            if (inBuffer.GetCapacity() < (int)sizeof(int) ||
                pOutBuffer->GetCapacity() < (int)sizeof(Camera_Format)) {
                ec = E_OUT_OF_MEMORY;
                break;
            }

            pFormat = (Camera_Format *)pOutBuffer->GetPayload();
            pFormat->nID = *(int *)inBuffer.GetPayload();

            ec = g_CameraDriver.CamDrv_GetAppFormat(pFormat->nID,
                    &pFormat->wParam, &pFormat->lParam);
            pOutBuffer->SetUsed(sizeof(Camera_Format));
            break;
        case 8:
            // Enter photo/video mode.
            // Default thhe driver enters photo mode.
            if (inBuffer.GetPayload() == NULL) {
                g_CameraDriver.CamDrv_SetCamMode(PHOTO_MODE);
            }
            else {
                g_CameraDriver.CamDrv_SetCamMode(*(int *)inBuffer.GetPayload());
            }
            break;

        case 9:{
            // Begin video record
            if (NULL == ppCompletionEvent) {
                ec = E_INVALID_ARGUMENT;
                break;
            }
            ec = g_CameraDriver.CamDrv_BeginVideoRecord(ppCompletionEvent);
            break;
        }

        case 10:
            // Stop video record
            ec = g_CameraDriver.CamDrv_StopVideoRecord();
            break;

        case 11:{
            // Get image frame information and data,
            Camera_ImageFrame *pFrame;
//WANGHAN change to easy use
//            if ((pOutBuffer == NULL) || (inBuffer.GetPayload() == NULL)){
//                ec = E_INVALID_ARGUMENT;
//                break;
//            }
            if (pOutBuffer == NULL){
                ec = E_INVALID_ARGUMENT;
                break;
            }
//WANGHAN080924
            if (pOutBuffer->GetCapacity() < (int)sizeof(Camera_ImageFrame)) {
                ec = E_OUT_OF_MEMORY;
                break;
            }

            pFrame = (Camera_ImageFrame *)pOutBuffer->GetPayload();
//WANGHAN change to easy use
            if(!pFrame || NULL == pFrame->pBuffer){
                ec = E_INVALID_ARGUMENT;
                break;
            }
//            pFrame->pBuffer = (void *)inBuffer.GetPayload();
//WANGHAN080924
            ec = g_CameraDriver.CamDrv_GetVideoFrame(pFrame);
            pOutBuffer->SetUsed(sizeof(Camera_ImageFrame));
            break;
        }

        case 100:{
            int iOn;
            if ((inBuffer.GetPayload() == NULL)
                && (inBuffer.GetCapacity() < (int)sizeof(int))){
                ec = E_INVALID_ARGUMENT;
                break;
            }
            iOn = *((int *)inBuffer.GetPayload());
// *  FLEDEnable     Flash LED ON : FLEDEnable = 1 ; Flash LED OFF : FLEDEnable = 0;
// *  Torch_mode      Torch mode : Torch_mode = 1 ; Flash mode : Torch_mode = 0;
            if(nu_CameraSetFlashLED(iOn, 1)){
                kprintf("nu_CameraSetFlashLED failed\n");
                ec = E_INVALID_OPERATION;
            }
            break;
        }
        case 111:{
            // Get image frame information and data,
            Camera_ImageFrame *pFrame;
//WANGHAN change to easy use
//            if ((pOutBuffer == NULL) || (inBuffer.GetPayload() == NULL)){
//                ec = E_INVALID_ARGUMENT;
//                break;
//            }
            if (pOutBuffer == NULL){
                ec = E_INVALID_ARGUMENT;
                break;
            }
//WANGHAN080924
            if (pOutBuffer->GetCapacity() < (int)sizeof(Camera_ImageFrame)) {
                ec = E_OUT_OF_MEMORY;
                break;
            }

            pFrame = (Camera_ImageFrame *)pOutBuffer->GetPayload();
//WANGHAN change to easy use
            if(NULL == pFrame->pBuffer){
                ec = E_INVALID_ARGUMENT;
                break;
            }
//            pFrame->pBuffer = (void *)inBuffer.GetPayload();
//WANGHAN080924
            ec = g_CameraDriver.CamDrv_GetPreviewFrame(pFrame);
            pOutBuffer->SetUsed(sizeof(Camera_ImageFrame));
            break;
            break;
        }
        // Power management code
        case 1000:
            break;

        case 1001:
        case 1002:
            break;

        default :
            ec = E_NOT_IMPLEMENTED;
            break;
    }

    return ec;
}

void CCamera::Dispose()
{
    delete this;
}

EXTERN IDeviceDriver * CDECL CreateCamera(uint_t uDeviceNo, void *pvParameter)
{
    CCamera* cam = new CCamera;
    if (!cam) {
        DRV_EXPRESSION(ERRORLEVEL, kprintf("Not enough memory\n"));
        return NULL;
    }

    cam->AddRef();
    kprintf("Create Camera OK!\n");
    return (IDeviceDriver *)cam;
}

